//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// cl_fit_mv - Ajusta curva de luz de binarias a dados observados utilizando
//			   Cadeias de Markov. 
// 
// Definicao das funcoes da classe PReader que le os parametros de entrada
// para programa de ajuste da curva de luz. Essa classe le e armazena os parametros
// de uma forma amigavel ao programa de modelagem de curva de luz. Alem disso, 
// a classe define a interface para passar os dados aos programas de modelagem
// atravez da funcao orgpar().
// 
//+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

//#include "cl_fit_input_funcs.hpp"
//#include "cl_fit_data_funcs.hpp"
//#include <exception>
#include "cl_fit_mc_v0_1.h"
#include "dataFileReader_v0.1.1/dataFileReader.h"
#include "light_curve.h"

using namespace std;

PReader::PReader(char* argv){
	
	if (!argv) {
		help_page(0);
	}
	
	if(!strcasecmp(argv,"-h")){
		help_page(-1);
	}
	// Input File Definition - IFD:  
	//     Number of fixed Parameters lines      -  IFD_NP
	//     Number of columns Parameters          - *IFD_P (array[IFD_NP])
	//     Spot Line(onde com. def. de spot - 1) -  IFD_SL
	//     Number of Spot Parameters             -  IFD_SP
	//     posicao da lei de obs. de Borda       -  IFD_B
	
	__IFDNP = 6;
	__IFDP = new int [__IFDNP];
	__IFDP[0] = 1;
	__IFDP[1] =5;
	__IFDP[2] =8;
	__IFDP[3] =8;
	__IFDP[4] =0;
	__IFDP[5] =0;
	__IFDSL = 6;
	__IFDSP = 5;
	__IFDB_1 = new int [3];
	__IFDB_2 = new int [3];
	__IFDB_1[0] = 5;
	__IFDB_1[1] = 2;
	__IFDB_1[2] = 2;
	__IFDB_2[0] = 4;
	__IFDB_2[1] = 3;
	__IFDB_2[2] = 2;
	_f0=-0.5;
	_f1=0.5;
	_df=0.01;
	
	//Leio parametros
	DataFileReader read(argv);
	_par.resize(__IFDNP);
	for(int i = 0; i < __IFDNP; i++){
		if(i==__IFDB_2[0]) __IFDP[4]=definicoes_obscurecimento(int(_par[__IFDB_2[1]][__IFDB_2[2]]));
		
		if(i==__IFDB_1[0]) __IFDP[5]=definicoes_obscurecimento(int(_par[__IFDB_1[1]][__IFDB_1[2]]));
		
		_par[i].resize(__IFDP[i]);
		++read;
		
		for(int j = 0; j < __IFDP[i]; j++){
			_par[i][j] = read.readColumn<double>(j+1);
			
		}
		
	}
	for(int i = __IFDNP; i < __IFDNP+nspot(); i++){
		_par.push_back(_par[0]);
		_par[i].resize(__IFDSP);
		++read;
		for(int j = 0; j < __IFDSP; j++)
			_par[i][j] = read.readColumn<double>(j+1);
	}
	read.close();
	//      cout<<"# - Parameters reading [DONE]\n";
/*	if(argc > 3){
		DataFileReader ffases(argv[3]);
		while(!++ffases)
			phases.push_back(ffases.readColumn<double>(1));
	}
	else for (double ff = _f0; ff <= _f1+_df; ff+=_df) phases.push_back(ff);
*/	
	//Parameters definitions
	_pardef.resize(_par.size());
	_pardef[0].push_back("nslices = ");
	
	_pardef[1].push_back("i = ");
	_pardef[1].push_back("M1 = ");
	_pardef[1].push_back("M2 = ");
	_pardef[1].push_back("P = ");
	_pardef[1].push_back("S/N = ");
	
	_pardef[2].push_back("f2 = ");
	_pardef[2].push_back("grav_coef2 = ");
	_pardef[2].push_back("limb_law2 = ");
	_pardef[2].push_back("nspot2 = ");
	_pardef[2].push_back("Tpole2 = ");
	_pardef[2].push_back("f_fac2 = ");
	_pardef[2].push_back("A2 = ");
	_pardef[2].push_back("Irr2 = ");
	
	_pardef[3].push_back("f1 = ");
	_pardef[3].push_back("grav_coef1 = ");
	_pardef[3].push_back("limb_law1 = ");
	_pardef[3].push_back("nspot1 = ");
	_pardef[3].push_back("Tpole1 = ");
	_pardef[3].push_back("f_fac1 = ");
	_pardef[3].push_back("A1 = ");
	_pardef[3].push_back("Irr1 = ");
	
	for(int i = 0; i < _par[4].size(); i++){
		ostringstream str0;
		str0 << "x" << i << " = ";
		_pardef[4].push_back(str0.str());
	}
	
	for(int i = 0; i < _par[5].size(); i++){
		ostringstream str0;
		str0 << "x" << i << " = ";
		_pardef[5].push_back(str0.str());
	}
	
	
	if(nspot() > 0){
		_pardef[6].push_back("theta = ");
		_pardef[6].push_back("phi = ");
		_pardef[6].push_back("dt = ");
		_pardef[6].push_back("dp = ");
		_pardef[6].push_back("Is = ");
	}
	
	//      cout << "# - Reading is done...\n";
}

int inline PReader::definicoes_obscurecimento(const int law)
{
	vector<vector<double> > par;
	
	Light_Curve teste(par);
	
	return teste.npar_obs_borda(law);
}

vector<vector<double> > inline PReader::org_par(int component = 0)
{
	vector<vector<double> > saida;
	if (component != 0 && component != 1) aborta("Component is either 0 or 1 ...")
		// saida[0] = par[1]
		saida.push_back(_par[1]);
	if (component == 1){// P/ component = 1 trocar M1 com M2
		saida[0][1] = _par[1][2];
		saida[0][2] = _par[1][1];
	} 
	//saida[1] = par[2] (se component = 0) ou = par[3] (se component = 1)
	saida.push_back(_par[2+component]);
	
	//saida[2] = par[4] (se component = 0) ou = par[5] (se component = 1)
	
	saida.push_back(_par[4+component]);
	//saida[3] ate saida[3+saida[1][3]] = par[6] ate par[6+par[2][3]] se component = 0
	// ou = par[6+par[2][3]] ate par[6+par[2][3]+par[3][3]] se component = 1
	if (component == 0){
		for (int i = 0; i < _par[2][3]; i++) {
			saida.push_back(_par[6+i]);
		}
	}
	if (component == 1) {
		for (int i = _par[2][3]; i < _par[3][3] ; i++) {
			saida.push_back(_par[6+i]);
		}
	}
	
	saida[0][0]*=M_PI/180.0; // transforma em radianos
	return saida;
}


